#include "CameraArea.h"
#include "CSceneObject.h"
#include "CLevelEditor.h"
#include "irrlicht.h"
#include <cmath>

extern CLevelEditor* editor;

CameraArea::CameraArea()
	:m_curEditCtrlPointIdx(-1),
	 m_isValid(false)
{
	for(int i=0; i<4; i++)
		m_ctrlPointObjs[i] = 0;
}

void CameraArea::InitFromOneOfContrlPointObj(CSceneObject* pCtrlPointObj)
{
	if(pCtrlPointObj==0)
		return;

	for(int i=0; i<4; i++)
		m_ctrlPointObjs[i] = 0;

	int caID = pCtrlPointObj->m_UserData->getAttributeAsInt("!^Owner^CameraArea");
	if(caID<0)
	{		
		//single point
		m_curEditCtrlPointIdx = 0;
		m_ctrlPointObjs[m_curEditCtrlPointIdx] = pCtrlPointObj;
		return;
	}

	CSceneObject* pObj = editor->getSceneObjectFromID(caID);
	if(pObj==0)
	{
		return;
	}
	
	char _tmp_buf[256];
	int cpNum = 0;
	for(int i=0; i<4; ++i)
	{
		sprintf_s(_tmp_buf,"^Point%d^CamCtrlPoint",(i+1));
		int ccpID = pObj->m_UserData->getAttributeAsInt(_tmp_buf);
		if(ccpID>=0)
		{
			CSceneObject* ccpObj= editor->getSceneObjectFromID(ccpID);
			if(ccpObj==pCtrlPointObj)
				m_curEditCtrlPointIdx = i;
			m_ctrlPointObjs[i] = ccpObj;
			cpNum++;
		}
	}
	
	if(cpNum==4)
		m_isValid = true;
}

void CameraArea::SnapTargetOffsetToNearEdge()
{
	if(!m_isValid || m_curEditCtrlPointIdx<0)
		return;

	//Note: about edge
	//we have four point 0, 1, 2, 3, so we have four edges: 0-1, 1-2, 2-3, 3-0
	
	//first, get the offset vector
	irr::core::vector3df targetOffset, targetPoint;
	targetOffset.set(
		m_ctrlPointObjs[m_curEditCtrlPointIdx]->m_UserData->getAttributeAsFloat("targetOffsetX"),
		m_ctrlPointObjs[m_curEditCtrlPointIdx]->m_UserData->getAttributeAsFloat("targetOffsetY"),
		m_ctrlPointObjs[m_curEditCtrlPointIdx]->m_UserData->getAttributeAsFloat("targetOffsetZ"));
	if(targetOffset.equals(irr::core::vector3df(0,0,0)))
		return;

	targetPoint = m_ctrlPointObjs[m_curEditCtrlPointIdx]->m_SceneNode->getAbsolutePosition() + targetOffset;

	//second, we need to find two edge of current control point
	int neighborPoint1 = m_curEditCtrlPointIdx-1;
	if(neighborPoint1<0)
		neighborPoint1=3;
	int neighborPoint2 = m_curEditCtrlPointIdx+1;
	if(neighborPoint2>3)
		neighborPoint2=0;

	irr::core::line3df edge1(m_ctrlPointObjs[m_curEditCtrlPointIdx]->m_SceneNode->getAbsolutePosition(),
							m_ctrlPointObjs[neighborPoint1]->m_SceneNode->getAbsolutePosition());

	irr::core::line3df edge2(m_ctrlPointObjs[m_curEditCtrlPointIdx]->m_SceneNode->getAbsolutePosition(),
							m_ctrlPointObjs[neighborPoint2]->m_SceneNode->getAbsolutePosition());

	irr::core::vector3df ptOnEdge1 = edge1.getClosestPoint(targetPoint);
	irr::core::vector3df ptOnEdge2 = edge2.getClosestPoint(targetPoint);

	irr::f32 disToEdge1 = targetPoint.getDistanceFrom(ptOnEdge1);
	irr::f32 disToEdge2 = targetPoint.getDistanceFrom(ptOnEdge2);

	if(disToEdge1<disToEdge2)
	{
		targetPoint = ptOnEdge1;
	}
	else
	{
		targetPoint = ptOnEdge2;
	}


	targetOffset = targetPoint - m_ctrlPointObjs[m_curEditCtrlPointIdx]->m_SceneNode->getAbsolutePosition();
	m_ctrlPointObjs[m_curEditCtrlPointIdx]->m_UserData->setAttribute("targetOffsetX",targetOffset.X);
	m_ctrlPointObjs[m_curEditCtrlPointIdx]->m_UserData->setAttribute("targetOffsetY",targetOffset.Y);
	m_ctrlPointObjs[m_curEditCtrlPointIdx]->m_UserData->setAttribute("targetOffsetZ",targetOffset.Z);
}